﻿using System;
using System.IO;
using UnityEditor;
using UnityEngine;
#if UNITY_2020_1_OR_NEWER
using UnityEngine.UIElements;
#else
using UnityEngine.Experimental.UIElements;
#endif

namespace E7.Protobuf
{
    internal static class ProtoPrefs
    {
        internal static readonly string prefProtocPref = "ProtobufUnity";

        public class ProtoPreset
        {
            public bool ProtocEnable = true;
            public bool LogError = true;
            public bool LogStandard = true;
            public string exe = "protogen";
            public string proto = "Proto";
            public string protocol = "Assets/TKC/Scripts/Network/Protocol";
            public string optioneasrch = "Server_Proj";
        }

        static ProtoPreset _Preset = null;

        static ProtoPreset Preset
        {
            get
            {
                if (_Preset == null)
                {
                    string s = EditorPrefs.GetString(prefProtocPref, "");
                    if (string.IsNullOrWhiteSpace(s))
                    {
                        _Preset = new ProtoPreset();
                        return _Preset;
                    }

                    _Preset = JsonUtility.FromJson<ProtoPreset>(s);
                }

                return _Preset;
            }
        }

        public static string excPath
        {
            get
            {
                if (Preset.exe.StartsWith("./"))
                    return Path.GetFullPath(Preset.exe);
                return Preset.exe;
            }
        }

        public static string rawProtoPath
        {
            get
            {
                if (Preset.proto.StartsWith("./") || Preset.proto.IndexOf(":") < 0)
                    return Path.GetFullPath(Preset.proto);
                return Preset.proto;
            }
        }

        public static string optionalSearchPath
        {
            get
            {
                if (string.IsNullOrEmpty(Preset.optioneasrch)) return "";
                if (Preset.optioneasrch.StartsWith("./") || Preset.optioneasrch.IndexOf(":") < 0)
                    return Path.GetFullPath(Preset.optioneasrch);

                return Preset.optioneasrch;
            }
        }

        public static string rawProtoCodePath
        {
            get
            {
                if (Preset.protocol.StartsWith("./") || Preset.protocol.IndexOf(":") < 0)
                    return Path.GetFullPath(Preset.protocol);

                return Preset.protocol;
            }
        }

        public static bool enabled
        {
            get { return Preset.ProtocEnable; }
        }

        public static bool logError
        {
            get { return Preset.LogError; }
        }

        public static bool logStandard
        {
            get { return Preset.LogStandard; }
        }


#if UNITY_2018_3_OR_NEWER
        internal class ProtobufUnitySettingsProvider : SettingsProvider
        {
            public ProtobufUnitySettingsProvider(string path, SettingsScope scope = SettingsScope.User)
                : base(path, scope)
            {
            }

            public override void OnGUI(string searchContext)
            {
                ProtobufPreference();
            }

            [SettingsProvider]
            static SettingsProvider ProtobufPreferenceSettingsProvider()
            {
                return new ProtobufUnitySettingsProvider("Preferences/Protobuf");
            }

            public override void OnActivate(string searchContext, VisualElement rootElement)
            {
                base.OnActivate(searchContext, rootElement);
                if (Preset == null)
                    _Preset = new ProtoPreset();
            }

            public override void OnDeactivate()
            {
                base.OnDeactivate();
                if (_Preset != null)
                    EditorPrefs.SetString(prefProtocPref, JsonUtility.ToJson(_Preset));
            }
        }
#else
        [PreferenceItem("Protobuf")]
#endif
        static void ProtobufPreference()
        {
            EditorGUI.BeginChangeCheck();

            Preset.ProtocEnable = EditorGUILayout.Toggle(new GUIContent("Enable Protobuf Compilation", ""), Preset.ProtocEnable);

            EditorGUI.BeginDisabledGroup(!Preset.ProtocEnable);

            EditorGUILayout.HelpBox(@"On Windows put the path to protoc.exe (e.g. C:\My Dir\protoc.exe), on macOS and Linux you can use ""which protoc"" to find its location. (e.g. /usr/local/bin/protoc)", MessageType.Info);

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Path to protoc", GUILayout.Width(100));
            Preset.exe = EditorGUILayout.TextField(Preset.exe, GUILayout.ExpandWidth(true));
            if (GUILayout.Button("浏览"))
            {
                string extension = "exe";
#if UNITY_EDITOR_OSX
                extension = "";
#endif
                string path = EditorUtility.OpenFilePanel("选择Pretogen.exe", Preset.exe, extension);
                if (!string.IsNullOrWhiteSpace(path))
                    Preset.exe = path;
            }

            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Path to proto", GUILayout.Width(100));
            Preset.proto = EditorGUILayout.TextField(Preset.proto, GUILayout.ExpandWidth(true));
            if (GUILayout.Button("浏览"))
            {
                string path = EditorUtility.OpenFolderPanel("选择目录(当前项目路径下)", Preset.proto, "");
                if (!string.IsNullOrWhiteSpace(path))
                    Preset.proto = path;
            }

            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("Path to cs Code", GUILayout.Width(100));
            Preset.protocol = EditorGUILayout.TextField(Preset.protocol, GUILayout.ExpandWidth(true));
            if (GUILayout.Button("浏览"))
            {
                string path = EditorUtility.OpenFolderPanel("选择目录(当前项目路径下)", Preset.protocol, "");
                if (!string.IsNullOrWhiteSpace(path))
                    Preset.protocol = path;
            }

            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("optional search Path", GUILayout.Width(100));
            Preset.optioneasrch = EditorGUILayout.TextField(Preset.optioneasrch, GUILayout.ExpandWidth(true));
            if (GUILayout.Button("浏览"))
            {
                string path = EditorUtility.OpenFolderPanel("选择目录(当前项目路径下)", Preset.optioneasrch, "");
                if (!string.IsNullOrWhiteSpace(path))
                    Preset.optioneasrch = path;
            }

            EditorGUILayout.EndHorizontal();

            EditorGUILayout.Space();

            Preset.LogError = EditorGUILayout.Toggle(new GUIContent("Log Error Output", "Log compilation errors from protoc command."), Preset.LogError);

            Preset.LogStandard = EditorGUILayout.Toggle(new GUIContent("Log Standard Output", "Log compilation completion messages."), Preset.LogStandard);

            EditorGUILayout.Space();

            if (GUILayout.Button(new GUIContent("Force Compilation")))
            {
                ProtobufUnityCompiler.CompileAllInProject();
            }

            EditorGUI.EndDisabledGroup();

            if (EditorGUI.EndChangeCheck())
            {
            }
        }

        [MenuItem("Tools/Protobuf/Gen C#")]
        static void ForceCompilation()
        {
            ProtobufUnityCompiler.CompileAllInProject();
        }

        [MenuItem("Tools/Protobuf/Setting")]
        static void Setting()
        {
#if UNITY_EDITOR_OSX
            EditorApplication.ExecuteMenuItem("Unity/Preferences...");
#elif UNITY_EDITOR_WIN
            EditorApplication.ExecuteMenuItem("Edit/Preferences...");
#endif
        }
    }
}